/**
 *  Serponix is an arcade game in focus to multiplayer based on the classic game Snake.
 *  Copyright (C) 2010 - 2011  Daniel Vala
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License,
 *  or  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  If you have any question do not hesitate to contact author
 *  on e-mail address: danielvala42@gmail.com
 */
package com.serponix.settings;

import com.serponix.game.Mode;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JOptionPane;

/**
 * Třída pro obsluhu práce s nastavením.
 * Obsahuje nastavení hry přístupné odkudkoliv.
 * Nastavení lze načíst ze souboru a uložit ho.
 * Aktuální nastavení lze nastavit do výchozího stavu.
 * Dále lze získat cestu ke všem uloženým souborům v uživatelské složce.
 * @author Daniel Vala
 */
public class SettingsFactory {

    private static NastaveniHry nastaveniHry;
    private static final String PATH;
    private static final String JMENO_SOUBORU = "settings.ser";
    private static final int pocetHracu = 4;
    private static final int[][] defaultniKlavesy = {{38, 40, 37, 39, 32, 17}, {87, 83, 65, 68, 49, 50}, {85, 74, 72, 75, 53, 54}, {104, 101, 100, 102, 34, 33}};
    private static final SnakeAction[] klavesy = {SnakeAction.UP, SnakeAction.DOWN, SnakeAction.LEFT, SnakeAction.RIGHT, SnakeAction.FIRE, SnakeAction.FIRE2};
    public static final int velikostPolicka = 10;

    static {
        PATH = getDirPath();
    }

    /**
     * Vrátí aktuální načtené nastavení hry v paměti.
     * @return Aktuální nastavení hry.
     */
    public static NastaveniHry getNastaveniHry() {
        return nastaveniHry;
    }

    /**
     * Zvolí cestu k uložení uživatelských souborů.
     * Ve Windows 7 je to složka My Games (umístěná v uživatelské složce).
     * V ostatních operačních systémech je to uživatelská složka.
     * @return Cestu k uložení uživatelských souborů.
     */
    public static String getDirPath() {
        if (System.getProperty("os.name").contains("Linux")) {
            return System.getProperty("user.home") + File.separator + "Serponix" + File.separator;
        } else if (System.getProperty("os.name").contains("Windows XP")) {
            return System.getProperty("user.home") + File.separator + "Serponix" + File.separator;
        } else if (System.getProperty("os.name").contains("Windows 7")) {
            return System.getProperty("user.home") + File.separator + "Documents" + File.separator + "My Games" + File.separator + "Serponix" + File.separator;
        } else {
            return System.getProperty("user.home") + File.separator + "Serponix" + File.separator;
        }
    }

    /**
     * Načte nastavení ze souboru do paměti.
     */
    public static void load() {
        if (!new File(PATH + JMENO_SOUBORU).exists()) {
            nastaveniHry = new NastaveniHry();
            setDefault();
            uloz();
        } else {
            ObjectInputStream input = null;
            try {
                input = new ObjectInputStream(new FileInputStream(new File(PATH + JMENO_SOUBORU)));
                nastaveniHry = (NastaveniHry) input.readObject();
            } catch (FileNotFoundException ex) {
                JOptionPane.showMessageDialog(null, "Nebyl nalezen soubor s nastavením hry.", "Chyba", JOptionPane.ERROR_MESSAGE);
                System.exit(1);
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(null, "Chyba čtení souboru nastavení. Zřejmě máte zastaralý soubor settings.ser. Smažte jej. \n (Umístění: " + PATH + JMENO_SOUBORU + ")", "Chyba", JOptionPane.ERROR_MESSAGE);
                System.exit(1);
            } catch (ClassNotFoundException ex) {
                JOptionPane.showMessageDialog(null, "Chyba čtení souboru nastavení. Zřejmě máte zastaralý soubor settings.ser. Smažte jej. \n (Umístění: " + PATH + JMENO_SOUBORU + ")", "Chyba", JOptionPane.ERROR_MESSAGE);
                System.exit(1);
            } finally {
                try {
                    input.close();
                } catch (IOException ex) {
                    JOptionPane.showMessageDialog(null, "Chyba při zavírání souboru nastavení.", "Chyba", JOptionPane.ERROR_MESSAGE);
                }
            }
        }
    }

    /**
     * Uloží aktuální nastavení z paměti do souboru.
     */
    public static void uloz() {
        new File(PATH).mkdirs();
        ObjectOutputStream output = null;
        try {
            output = new ObjectOutputStream(new FileOutputStream(new File(PATH + JMENO_SOUBORU)));
            output.writeObject(nastaveniHry);
        } catch (FileNotFoundException ex) {
            JOptionPane.showMessageDialog(null, "Ověřte, že máte do oprávnění do složky " + PATH, "Chyba", JOptionPane.ERROR_MESSAGE);
            System.exit(1);
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(null, "Ověřte, že máte do oprávnění do složky " + PATH, "Chyba", JOptionPane.ERROR_MESSAGE);
            System.exit(1);
        } finally {
            try {
                if (output != null) {
                    output.close();
                }
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(null, "Chyba při zavírání souboru nastavení.", "Chyba", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    /**
     * Nastaví aktuální nastavení v paměti na výchozí hodnoty.
     */
    public static void setDefault() {
        nastaveniHry.setRychlost(60);
        nastaveniHry.setServerIP("");
        nastaveniHry.setJmeno(0, System.getProperty("user.name"));
        nastaveniHry.setJmeno(1, "hráč 2");
        nastaveniHry.setJmeno(2, "hráč 3");
        nastaveniHry.setJmeno(3, "hráč 4");
        nastaveniHry.setPocetHracu(2);
        nastaveniHry.setPort(56429);
        nastaveniHry.setMod(Mode.FUN_MOD);

        List<Map<SnakeAction, Integer>> vsechnyKlavesy = new ArrayList<Map<SnakeAction, Integer>>();
        for (int i = 0; i < pocetHracu; i++) {
            vsechnyKlavesy.add(new HashMap<SnakeAction, Integer>());
        }
        nastaveniHry.setVsechnyKlavesy(vsechnyKlavesy);

        for (int j = 0; j < pocetHracu; j++) {
            for (int i = 0; i < klavesy.length; i++) {
                nastaveniHry.getVsechnyKlavesy().get(j).put(klavesy[i], defaultniKlavesy[j][i]);
            }
        }
    }
}
